<?php

/**
 * @desc Backend list. 
 *
 */
class Backend_Component_List extends Kernel_Action_List 
{

    /**
     * Actions list that can be hold on the elements of the list. 
     *
     * @param array
     */
    public $actions = array();
    
    /**
    * @desc If this param is FALSE then try to add table postfix. Change it to 
    * TRUE if there's no need to add language postfix.
    * 
    * @param boolean
    */
    public $no_postfix = false;

    /**
     * Path to the template file. 
     *
     * @param string
     */
    protected $_template = 'backend/component/list.tpl';

    /**
     * @desc Define table in case of automatic build for SQL statement. 
     *
     * @param string
     */
    protected $_table;

    /**
     * @desc List columns. 
     *
     * @param array
     */
    protected $_columns = array();

    /**
     * @desc Primary key. 
     *
     * @param mixed
     */
    protected $_key = 'id';

    /**
     * @desc SQL WHERE statement. 
     *
     * @param string
     */
    protected $_where;

    /**
     * @desc SQL ORDER field. 
     *
     * @param string
     */
    protected $_order;

    /**
     * @desc Sort fields mapping on the SQl statement. 
     *
     * @param array
     */
    protected $_order_map = array();

    /**
     * @desc Name for the URI param holds action name. Can be changed for nested 
     * lists. 
     *
     * @param string
     */
    protected $_action_param = 'action';

    /**
     * @desc Fields' list for which reverse order is held. 
     *
     * @param array
     */
    protected $_reverse = array();

    /**
     * @desc Output direction: true - stright, false - reverse. 
     *
     * @param boolean
     */
    private $_direction;

    /**
     * @desc No order fields. 
     *
     * @param array
     */
    private $_no_order = array(); 
    


    
    public function __construct($params = array()) 
    {
        // in case of actions' definition in child set them
        if (array_key_exists('actions', $params)) {
            $params['actions'] = array_merge($params['actions'], (array)$this->actions);
        }
        parent::__construct($params);
        
        $this->_no_order = array_keys(array_filter($this->_order_map, create_function('$value', 'return false === $value;')));
        
        // if table is defined then add prefix if needed
        if (!is_null($this->_table) && !$this->no_postfix) {
            $this->_table = __postfix($this->_table);
        }
    }

    /**
     * @desc User processing. 
     *
     */
    protected function _process() 
    {
        if (empty($this->_columns)) {
            trigger_error('Columns must be specified in class definition', E_USER_ERROR);
        }

        $request = Application::getRequest();

        $this->_order = $request->get('order', null !== ($this->_order)
            ? $this->_order
            : reset($this->_columns));

        if (!in_array($this->_order, array_merge((array)$this->_key, $this->_columns)) || 
            in_array($this->_order, $this->_no_order)) 
        {
            $this->_abort('Incorrect order specified');
        }

        switch ($request->get('direction')) {
            case 'asc':
                $this->_direction = true;
                break;
            case 'desc':
                $this->_direction = false;
                break;
            default:
                $this->_direction = !in_array($this->_order, $this->_reverse);
                break;
        }

        parent::_process();

        Application::getResponse()->assign('list', array(
            'columns' => $this->_columns,
                'key' => (array)(null !== $this->_key ? $this->_key : reset($this->_columns)),
              'order' => $this->_order,
          'direction' => $this->_direction,
            'actions' => $this->_getActions(),
           'disabled' => $this->_getDisabled(),
            'noorder' => $this->_no_order,
        ));
    }

    /**
     * Form SQl statement. 
     *
     * @return  string
     */
    protected function _getQueryBody() 
    {
        if (!is_string($this->_table)) {
            trigger_error('Table must be specified in class definition', E_USER_ERROR);
        }

        $query = 'SELECT SQL_CALC_FOUND_ROWS
                         `' . implode('`, `', array_merge((array)$this->_key, $this->_columns)) . '`
                    FROM
                         `' . $this->_table . '`';

        if (!is_null($this->_where)) {
            $query .= '
                   WHERE
                         ' . $this->_where;
        }
        
        return $query .= $this->_getOrder();
    }

    /**
     * @desc Return SQL statement order part. 
     *
     * @return  string
     */
    protected function _getOrder() 
    {
        $order = '';
        if (!is_null($this->_order)) {
            $order .= '
                ORDER BY
                         ' . (isset($this->_order_map[$this->_order])
                ? $this->_order_map[$this->_order]
                : '`' . $this->_order . '`');

            if (!$this->_direction) {
                $order .= ' DESC';
            }
        }
        return $order;
    }

    /**
     * @desc Return actions list. 
     *
     * @return  array
     */
    protected function _getActions() 
    {
        $actions = array();
        foreach ($this->actions as $name => $params) {
            $actions[$name] = empty($params)
                ? array($this->_action_param => $name) : $params;
        }
        return $actions;
    }

    /**
     * @desc Return array of actions and records' keys for which this actions 
     * are disabled.
     *
     * @return  array
     */
    protected function _getDisabled() 
    {
        return array();
    }
    
}
